<?php

declare(strict_types=1);

namespace NanQi\Hope\Di;

use Carbon\Carbon;
use Hyperf\Crontab\Crontab;
use Hyperf\Crontab\PipeMessage;
use Hyperf\Crontab\Strategy\AbstractStrategy;
use Hyperf\Crontab\Strategy\WorkerStrategy;
use NanQi\Hope\Crontab\Batch\BaseBatchCron;
use NanQi\Hope\Crontab\Batch\BatchCrontab;
use NanQi\Hope\Crontab\CrontabExecutor;
use NanQi\Hope\Helper;
use Swoole\Server;

class CrontabStrategy extends WorkerStrategy
{
    use Helper;

    public function dispatch(Crontab $crontab)
    {
        if ($crontab->getExecuteTime() instanceof Carbon) {
            $this->runCrontab($crontab);
        }
    }

    public function runCrontab(Crontab $crontab, string $method = 'execute')
    {
        $server = $this->getServer();
        if ($server instanceof \Swoole\Coroutine\Http\Server) {
            /** @var CrontabExecutor $executor */
            $executor = di(CrontabExecutor::class);
            $executor->execute($crontab);
            return;
        }

        $callback = $crontab->getCallback();
        if (count($callback) != 2) {
            throw new \InvalidArgumentException('crontab callback error');
        }

        $cron = di($callback[0]);
        if ($cron instanceof BaseBatchCron) {
            $workerId = 0;
        }  else {
            $workerId = $this->getNextWorkerId($server);
        }

        if ($server instanceof Server) {
            $server->sendMessage(new PipeMessage(
                'callback',
                [CrontabExecutor::class, $method],
                $crontab
            ), $workerId);
        }
    }
}
